'''
Created on Aug 13, 2012

@author: petrina
'''

import logging
import datetime
from error.data_exceptions import Record_exception


class Interval_list(object):
    '''
    List of agg_records measured at a specific time interval.
    
    Objects of this class are used from the record_list.
    '''
    
    
    def __init__(self, interval = 0):
        '''
        @param interval: time interval (default: 0)
        '''
        
        # the internal structure is a dict
        self._recordlist = []
        self.interval = interval
        
        logging.debug("Interval_list: created new Interval_list")


    #-----------------------getter- and setter-methods-------------------------

    def get_interval(self):
        return self.__interval


    def set_interval(self, value):
        self.__interval = value


    def del_interval(self):
        del self.__interval


    def get_begintime(self):
        '''
        searches for and returns the earliest record.
        
        @return: agg_record, if there is no record in the list the method returns None.
        '''
        if len(self._recordlist) > 0:
            time = datetime.datetime.now()
            
            # search for the oldest timestamp
            for rec in self._recordlist:
                if rec.timestamp < time:
                    time =rec.timestamp
            return time
        else:
            return None


    def get_endtime(self):
        '''
        searches for and returns the most recent record.
        
        @return: agg_record, if there is no record in the list the method returns None.
        '''
        
        if len(self._recordlist) > 0:        
            time = datetime.datetime(1900,1,1)
            
            # search for the newest timestamp
            for rec in self._recordlist:
                if rec.timestamp > time:
                    time =rec.timestamp
            return time
        else:
            return None

        
    #----------------------public methods of the class-------------------------
    
    def __iter__(self):
        return self._recordlist.__iter__()
    
    
    def next(self):
        pass
    
    
    def __getitem__(self, key):
        return self._recordlist[key]
    
    
    def items(self):
        return self._recordlist.items()
    
    
    def __len__(self):
        return len(self._recordlist)
   
    
    def plot(self, plotobject, attribute = "speed", color = 'blue'):
        '''
        plots the records of the list into a given plot (as points with '+' as marker).
        
        The method does not initialize a new figure.
        
        @param plotobject: object that offers plotting features (e.g. Plot)
        @param attribute: attribute that shall be plotted such as speed or travel time (default: speed)
        @param color: plotting color (default: blue)  
        '''
        
        for rec in self._recordlist:
                plotobject.plot(self.__interval, 
                                getattr(rec, attribute), 
                                col = color, 
                                mark='+', 
                                markersize = 4)
        
    
    def add_record(self, record):
        '''
        This method adds a Link-record-object to the record_list. 
        
        Therefore the record shall be of the type agg_record.
        The record-object must have an interval-attribute in order 
        to check if they can be added to this list. 
        The list only takes records of one specific interval.
        '''
        
        try:
            
            if record.interval == self.__interval:
                self._recordlist.append(record)
                logging.debug("Interval_list: new record was added to the interval sorted Record_list " + record.__str__())
            else:
                # the error is ignored
                logging.error("Interval_list: cannot add the given object to the Record_list because it has the wrong time interval: " + str(record))
                raise Record_exception("cannot add the given object to the Record_list")
        except:
            # obviously no record-instance, the error is ignored
            logging.error("Interval_list: cannot add the given object to the Record_list: " + str(record))
            raise Record_exception("cannot add the given object to the Record_list")
    
    
    def search_data(self, date):
        '''
        searches the list for data on one specific day.
        
        The method returns the first found value. Multiple values are not supposed to be in the list
        because agg_records are already aggregated. 
        
        @param date: date-object for searching 
        @return: found record or None
        '''
        
        logging.debug("Interval_list: searching for data on this date " + date.__str__())

        for rec in self._recordlist:
            if rec.timestamp.day == date.day and rec.timestamp.year == date.year:
                logging.debug("Interval_list: found day data " + rec.__str__())
                return rec
        
        logging.debug("Interval_list: cannot find any  data on this day -- returning NONE :(")
        return None
    
    
    def create_value_list(self, starttime, endtime, attribute = 'speed'):
        '''
        builds a list of data from the given interval-list and attribute between the star- and endtime with the length of n days.
        
        If a day has no data, the value will be set None. Therefore several
        lists can be compared, so that the same days are compared.
        Otherwise lists of reference data and regular data might be of different lengths
        (because of missing value) and useless for comparing them by index.
        
        @param starttime: earliest date (date-object)
        @param endtime: most recent date (date-object)
        @param attribute: attribute of the Agg_record, which is added to the list
        @return: list of the attribute values for every day in that time interval/Interval_list
        '''
        
        # fill the data into this (usually it contains numeric values, no complex objects)
        new_data = []
        
        date = starttime
        # for every day
        while date <= endtime: 
            # get the value or append None (as place holder for the missing value)
            rec = self.search_data(date)
            new_data.append(None if rec is None else getattr(rec, attribute))
            
            # increase by one day
            date += datetime.timedelta(days=1)
        
        return new_data
                   
        
    #--------------assign properties using get and set-methods-----------------

    begintime = property(get_begintime, None, None, "timestamp of the earliest record (calculated from input data)")
    endtime = property(get_endtime, None, None, "timestamp of the most up-to-date-record (calculated from input data)")
    interval = property(get_interval, set_interval, del_interval, "time interval")
